package com.example.demo1.service.impl.service.impl;

import com.example.demo1.common.ResponseCode;
import com.example.demo1.common.ServerResponse;
import com.example.demo1.entity.BaMenu;
import com.example.demo1.mapper.BaMenuMapper;
import com.example.demo1.service.impl.service.MenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.util.*;

@Service
@Transactional
public class MenuServiceImpl implements MenuService {

    private Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);

    @Autowired
    private BaMenuMapper menuMapper;

    @Override
    public ServerResponse addMenu(BaMenu menu) {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.addMenu方法调用开始");

        menu.setState("0"); // 生效标识：0（默认）生效；1 失效
        menu.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        int result = menuMapper.insert(menu);
        if(result != 1){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.addMenu方法新增菜单失败");
            return ServerResponse.createByErrorMessage("新增菜单失败");
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.addMenu方法成功");
        return ServerResponse.createBySuccess("新增菜单成功");
    }

    @Override
    public ServerResponse validateMenuName(String menuName) {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuName方法调用开始");

        if(StringUtils.isEmpty(menuName)){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuName方法参数错误");
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        BaMenu menu = menuMapper.validateMenuName(menuName);
        if(menu != null){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuName方法菜单名称已存在");
            return ServerResponse.createByErrorMessage("菜单名称已存在");
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuName方法成功");
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse deleteMenu(Integer menuId) {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.deleteMenu方法调用开始");

        if(menuId == null){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.deleteMenu方法参数错误");
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        List<BaMenu> subMenus = menuMapper.hasSunMenus(menuId);
        if(!CollectionUtils.isEmpty(subMenus)){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.deleteMenu方法删除含有子菜单的菜单报错");
            return ServerResponse.createByErrorMessage("该菜单下含有其他子菜单，请先删除全部子菜单后再行删除该菜单");
        }
        int result = menuMapper.deleteByPrimaryKey(menuId);
        if(result != 1){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.deleteMenu方法删除菜单失败");
            return ServerResponse.createByErrorMessage("删除菜单失败");
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.deleteMenu方法成功");
        return ServerResponse.createBySuccess("删除菜单成功");
    }

    @Override
    public ServerResponse updateMenu(BaMenu menu) {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.updateMenu方法调用开始");

        if(menu.getMenuId() == null){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.updateMenu方法参数错误");
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        menu.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        int result = menuMapper.updateByPrimaryKeySelective(menu);
        if(result != 1){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.updateMenu方法修改菜单失败");
            return ServerResponse.createByErrorMessage("修改菜单失败");
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.updateMenu方法成功");
        return ServerResponse.createBySuccess("修改菜单成功");
    }

    @Override
    public ServerResponse validateMenuNameExSelf(String menuName, Integer menuId) {
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuNameExSelf方法调用开始");

        if(StringUtils.isEmpty(menuName)){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuNameExSelf方法参数错误");
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        BaMenu menu = menuMapper.validateMenuNameExSelf(menuName, menuId);
        if(menu != null){
            logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuNameExSelf方法菜单名称已存在");
            return ServerResponse.createByErrorMessage("菜单名称已存在");
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.validateMenuNameExSelf方法成功");
        return ServerResponse.createBySuccess();
    }

    @Override
    public List<BaMenu> getAllMenus() {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.getAllMenus方法调用开始");

        List<BaMenu> menus = menuMapper.findAll();
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.getAllMenus方法成功");
        return menus;
    }

    @Override
    public ServerResponse<List<BaMenu>> getUserRightMenus(Integer userId) {

        logger.info("时间：" + new Date() + "=================MenuServiceImpl.getUserMenuList方法调用开始");

        List<BaMenu> all = menuMapper.findAll();
        Map<Integer, BaMenu> menuInfoMap = new HashMap<>();
        for(BaMenu baMenuInfo : all){
            menuInfoMap.put(baMenuInfo.getMenuId(), baMenuInfo);
        }
        List<BaMenu> baMenuInfos = menuMapper.findUserRightMenus(userId);
        Set<BaMenu> set = new HashSet<>();
        for(BaMenu baMenuInfo : baMenuInfos){
            findParents(set, menuInfoMap, baMenuInfo);
        }
        Set<BaMenu> result = toTreeList(set);
        List<BaMenu> sortResult = new ArrayList<>();
        sortResult.addAll(result);
        Collections.sort(sortResult, new Comparator<Object>(){
            public int compare(Object o1, Object o2){
                BaMenu baMenuInfo1 = (BaMenu) o1;
                BaMenu baMenuInfo2 = (BaMenu) o2;
                return baMenuInfo1.getSortNum()-baMenuInfo2.getSortNum();//然后return一个int型的值
            }
        });
        for(BaMenu baMenuInfo : sortResult){
            sortList(baMenuInfo.getNodes());
        }
        logger.info("时间：" + new Date() + "=================MenuServiceImpl.getUserMenuList方法成功");
        return ServerResponse.createBySuccess(sortResult);
    }

    private void findParents(Set<BaMenu> set ,Map<Integer, BaMenu> all, BaMenu baMenuInfo){
        if(baMenuInfo.getParentId() != 0){
            set.add(all.get(baMenuInfo.getMenuId()));
            set.add(all.get(baMenuInfo.getParentId()));
            findParents(set, all, all.get(baMenuInfo.getParentId()));
        }else{
            set.add(all.get(baMenuInfo.getMenuId()));
        }
    }

    private void sortList(List<BaMenu> nodes){
        if(nodes.size() > 0){
            Collections.sort(nodes, new Comparator<Object>() {
                public int compare(Object o1, Object o2) {
                    BaMenu baMenuInfo1 = (BaMenu) o1;
                    BaMenu baMenuInfo2 = (BaMenu) o2;
                    return baMenuInfo1.getSortNum() - baMenuInfo2.getSortNum();//然后return一个int型的值
                }
            });
            for(BaMenu baMenuInfo : nodes){
                sortList(baMenuInfo.getNodes());
            }
        }
    }

    private Set<BaMenu> toTreeList(Set<BaMenu> baList) {
        Map<Object, BaMenu> maps = new HashMap<>();
        Set<BaMenu> set = new HashSet<>();
        for (BaMenu ba : baList) {
            addTreeNode(ba,maps,set);
        }
        return set;
    }

    private void addTreeNode(BaMenu ba, Map<Object, BaMenu> maps, Set<BaMenu> set) {
        if(maps.containsKey(ba.getMenuId())){
            maps.get(ba.getMenuId()).setEntity(ba);
        }else{
            maps.put(ba.getMenuId(), ba);
        }
        if(ba.getParentId() == 0){
            set.add(maps.get(ba.getMenuId()));
        }else{
            if(maps.containsKey(ba.getParentId())){
                maps.get(ba.getParentId()).addNode(maps.get(ba.getMenuId()));
            }else{
                BaMenu parent = new BaMenu();
                parent.addNode(ba);
                maps.put(ba.getParentId(),parent);
            }
        }
    }

}
